package com.thinkit.cms.service.admin;

import com.google.common.collect.Lists;
import com.thinkit.cms.api.admin.ApiClientService;
import com.thinkit.cms.api.admin.ApiSourceService;
import com.thinkit.cms.dto.admin.ApiClientDto;
import com.thinkit.cms.dto.admin.ApiSourceDto;
import com.thinkit.cms.entity.admin.ApiSource;
import com.thinkit.cms.mapper.admin.ApiSourceMapper;
import com.thinkit.core.base.BaseServiceImpl;
import com.thinkit.core.constant.Constants;
import com.thinkit.core.handler.CustomException;
import com.thinkit.utils.model.ApiResult;
import com.thinkit.utils.model.Tree;
import com.thinkit.utils.utils.BuildTree;
import com.thinkit.utils.utils.Checker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author LG
 * @since 2020-04-24
 */
@Transactional
@Service
public class ApiSourceServiceImpl extends BaseServiceImpl<ApiSourceDto, ApiSource, ApiSourceMapper> implements ApiSourceService {


    @Autowired
    ApiClientService apiClientService;

    @Override
    public Tree<ApiSourceDto> selectTreeList() {
        Map<String, Object> map = new HashMap<>(16);
        List<ApiSourceDto> menus = listDtoByMap(map);
        if (menus != null && !menus.isEmpty()) {
            List<Tree<ApiSourceDto>> trees = new ArrayList<Tree<ApiSourceDto>>();
            for (ApiSourceDto apiSourceDto : menus) {
                Tree<ApiSourceDto> tree = new Tree<ApiSourceDto>();
                tree.setId(apiSourceDto.getId());
                tree.setKey(apiSourceDto.getId());
                tree.setParentId(apiSourceDto.getParentId());
                tree.setName(apiSourceDto.getApiName());
                tree.setSpread(true);
                Map<String, Object> attributes = new HashMap<>(16);
                attributes.put("url", apiSourceDto.getApiUrl());
                attributes.put("apiModule", apiSourceDto.getApiModule());
                attributes.put("perms", apiSourceDto.getApiPerm());
                attributes.put("type", apiSourceDto.getApiType());
                attributes.put("orderNum", apiSourceDto.getApiOrderNum());
                tree.setAttributes(attributes);
                trees.add(tree);
            }
            Tree<ApiSourceDto> t = BuildTree.build(trees,true);
            return t;
        } else {
            Tree<ApiSourceDto> root = new Tree<ApiSourceDto>();
            root.setId("-1").setParentId("0").setHasParent(false).setHasChildren(true).setChildren(Lists.newArrayList())
            .setName("全 部")
            .setChecked(true);
            return root;
        }
    }


    @Override
    public boolean deleteById(String id) {
        ApiSourceDto apiSourceDto=getByPk(id);
        if(apiSourceDto.getApiType().intValue()==0){
            List<ApiSourceDto> apiSourceDtos= listByField("parent_id",id);
            if(Checker.BeNotEmpty(apiSourceDtos)){
                throw new CustomException(ApiResult.result(20010));
            }
        }
        return deleteByPk(id);
    }



    @Override
    public Tree<ApiSourceDto> selectTreeResourceByClientId(String clientId) {
        //给菜单分配权限时，首先查询该用户是否是超级管理员（id=1） ,超级管理员查询全部菜单，非超级管理员值查询自己拥有的权限
        Map<String, Object> param = new HashMap<>();
        List<ApiSourceDto> resources = new ArrayList<>();
        resources = super.listDtoByMap(param);
        List<String> resourceIds = apiClientService.selectResources(clientId);//查询当前client 所拥有的资源用于编辑时还原勾选状态
        List<Tree<ApiSourceDto>> trees = new ArrayList<Tree<ApiSourceDto>>();
        for (ApiSourceDto resource : resources) {
            String typeName = "";
            if (resource.getApiType() == 0) typeName = "(服务)";
            if (resource.getApiType() == 1) typeName = "(接口)";
            Tree<ApiSourceDto> tree = new Tree<ApiSourceDto>();
            tree.setKey(resource.getId());
            tree.setId(resource.getId());
            tree.setParentId(resource.getParentId());
            tree.setTitle(resource.getApiName() + typeName);
            trees.add(tree);
        }
        List<Tree<ApiSourceDto>> topNodes = BuildTree.buildList(trees, "0");
        Tree<ApiSourceDto> root = new Tree<ApiSourceDto>();
        if (topNodes.size() == 1) {
            root = topNodes.get(0);
        } else {
            root.setKey("-1");
            root.setId("-1");
            root.setParentId("0");
            root.setHasParent(false);
            root.setHasChildren(true);
            root.setChildren(topNodes);
            root.setTitle("顶级节点");
        }
        if (Checker.BeNotEmpty(resourceIds)) {
            Map<String, Object> attr = new HashMap<>(16);
            attr.put("checkerKeys", resourceIds);
            root.setAttributes(attr);
        }
        return root;
    }

    @Cacheable(value= Constants.cacheName, key="#root.targetClass+'.'+#root.methodName+'.'+#p0+'.'+#p1",unless="#result == null")
    @Override
    public Set<String> selectAppPermsByUrl(String url, String application) {
        List<String> perms = baseMapper.selectAppPermsByUrl(url,application);
        Set<String> permsSet = new HashSet<>();
        if(Checker.BeNotEmpty(perms)){
            for (String perm : perms) {
                if (Checker.BeNotBlank(perm)) {
                    permsSet.addAll(Arrays.asList(perm.trim().split(",")));
                }
            }
        }
        return permsSet;
    }

    @Cacheable(value= Constants.cacheName, key="#root.targetClass+'.'+#root.methodName+'.'+#p0+'.'+#p1",unless="#result == null")
    @Override
    public Set<String> selectAppPermsByClient(String clientId, String application) {
        return baseMapper.selectAppPermsByClient(clientId,application);
    }

    @Override
    public void save(ApiSourceDto v) {
        if (Checker.BeNotBlank(v.getParentId()) && !"0".equals(v.getParentId())) {
            checkerHasResource(v.getApiModule(),v.getApiUrl(),v.getApiPerm(),null);
            List<ApiClientDto> apiSourceClients = apiClientService.getsByApiId(v.getParentId());
            if (Checker.BeNotEmpty(apiSourceClients)) {
                apiSourceClients.forEach(apiSourceClient -> {
                    apiSourceClient.setHalfChecked(0);
                });
                apiClientService.updateByPks(apiSourceClients);
            }
        }
        super.insert(v);
    }

    @Override
    public void update(ApiSourceDto v) {
        if (Checker.BeNotBlank(v.getParentId()) && !"0".equals(v.getParentId())) {
            checkerHasResource(v.getApiModule(),v.getApiUrl(),v.getApiPerm(),v.getId());
        }
        super.updateByPk(v);
    }

    @Override
    public ApiSourceDto getById(String id) {
        return super.getByPk(id);
    }

    private void checkerHasResource(String application,String url,String perm,String id){
         int count= baseMapper.checkerHasResource(application,url,perm,id);
         if(count>0){
             throw  new  CustomException(ApiResult.result(5008));
         }
    }

}
